/*
*******************************************************************************
** Copyright (C), 2014-2020, TONLY AV R&D CENTER SOFTWARE DEVELOPMENT DEPARTMENT
** FileName: 
** <author>:             
** Date:
** Description:
**
** Others:
** Function List:
**   1.
** History:
**  <Author>    <date>    <content>    <version>
*******************************************************************************
*/
//*****************************************************************************
// File Include
//*****************************************************************************
#include "cdn_nvm3.h"
#include "em_wdog.h"
#include "cdn_light.h"
//*****************************************************************************
// Local Defines
//*****************************************************************************
// Maximum number of data objects saved
#define MAX_OBJECT_COUNT    64

// Max and min keys for data objects
#define MIN_DATA_KEY  NVM3_KEY_MIN
#define MAX_DATA_KEY  (MIN_DATA_KEY + MAX_OBJECT_COUNT - 1)

// Key of write counter object
#define WRITE_COUNTER_KEY   MAX_OBJECT_COUNT

// Key of delete counter object
#define DELETE_COUNTER_KEY   (WRITE_COUNTER_KEY + 1)

// Use the default nvm3 handle from nvm3_default.h
#define NVM3_DEFAULT_HANDLE nvm3_defaultHandle

//*****************************************************************************
// API Functions
//*****************************************************************************
void cdn_nvm3_init(void)
{
	uint32_t type;
  size_t len;
  Ecode_t err;

  // This will call nvm3_open() with default parameters for
  // memory base address and size, cache size, etc.
  err = nvm3_initDefault();
  EFM_ASSERT(err == ECODE_NVM3_OK);
  printf("zsm: cdn_nvm3_init success !\r\n");

	// check if the designated keys contain counters, and initialise if needed.
  err = nvm3_getObjectInfo(NVM3_DEFAULT_HANDLE, WRITE_COUNTER_KEY, &type, &len);
  if ((err != ECODE_NVM3_OK) || (type != NVM3_OBJECTTYPE_COUNTER)) {
    nvm3_writeCounter(NVM3_DEFAULT_HANDLE, WRITE_COUNTER_KEY, 0);
  }

  err = nvm3_getObjectInfo(NVM3_DEFAULT_HANDLE, DELETE_COUNTER_KEY, &type, &len);
  if ((err != ECODE_NVM3_OK) || (type != NVM3_OBJECTTYPE_COUNTER)) {
    nvm3_writeCounter(NVM3_DEFAULT_HANDLE, DELETE_COUNTER_KEY, 0);
  }
}

void cdn_nvm3_write(uint8_t key,uint8_t *data,size_t len)
{
  if (key > MAX_DATA_KEY)
  {
    printf("zsm: Invalid nvm_key\r\n");
    return;
  }
  if (len > NVM3_DEFAULT_MAX_OBJECT_SIZE)
  {
    printf("zsm: Maximum object size exceeded\r\n");
    return;
  }

  Ecode_t err = nvm3_writeData(NVM3_DEFAULT_HANDLE,
                               key,
                               (unsigned char *)data,
                               len);
  if (ECODE_NVM3_OK == err)
  {
    printf("zsm: Stored data at nvm_key = %d\r\n", key);
  }
  else
  {
    printf("zsm: Error storing data ErrorId = 0x%lx \r\n",err);
  }
}

void cdn_nvm3_read(uint8_t key,char *buffer)
{
  uint32_t type;
  size_t len;
  Ecode_t err;

  if (key > MAX_DATA_KEY)
  {
    printf("zsm: Invalid nvm_key\r\n");
    return;
  }

  err = nvm3_getObjectInfo(NVM3_DEFAULT_HANDLE, key, &type, &len);
  if (err != NVM3_OBJECTTYPE_DATA || type != NVM3_OBJECTTYPE_DATA)
  {
    printf("zsm: Key does not contain data object nvm_key = %d,len = %d \r\n",key,len);
    return;
  }

  err = nvm3_readData(NVM3_DEFAULT_HANDLE, key, buffer, len);
  if (ECODE_NVM3_OK == err)
  {
    //buffer[len] = '\0';
    printf("zsm: Read data Success from nvm_key = %d,len = %d\r\n", key,len);
    //printf("%s\r\n", buffer);
  }
  else
  {
    printf("zsm: Error reading data from nvm_key = %d,ErrorID = 0x%lx \r\n", key,err);
  }
}

void cdn_nvm3_delete(uint8_t key)
{
  if (key > MAX_DATA_KEY) {
    printf("zsm: Invalid nvm_key\r\n");
    return;
  }

  Ecode_t ErrorId = nvm3_deleteObject(NVM3_DEFAULT_HANDLE, key);
  if (ECODE_NVM3_OK == ErrorId)
  {
    printf("zsm: Deleted data at nvm_key = %d\r\n", key);
  }
  else
  {
    printf("zsm: Error deleting nvm_key = %d ,Error ID = 0x%lx \r\n",key,ErrorId);
  }
}

void cdn_nvm3_erase_custom_flash(void)
{
  printf("zx: cdn_light_erase_flash_save_info!\n");
	
	for(uint8_t i = 0;i < FLASH_KEY_ID_MAX;i++)
	{
  	cdn_nvm3_delete(i+1);
	}
}

/***************************************************************************//**
 * NVM3 ticking function.
 ******************************************************************************/
void cdn_nvm3_process_action(void)
{
  // Check if NVM3 controller can release any out-of-date objects
  // to free up memory.
  // This may take more than one call to nvm3_repack()
  while (nvm3_repackNeeded(NVM3_DEFAULT_HANDLE))
  {
    printf("zsm: Light Repacking NVM...\r\n");
		WDOGn_Feed(DEFAULT_WDOG);
		
    nvm3_repack(NVM3_DEFAULT_HANDLE);
  }
}

Ecode_t CdnNvm3repack(void)
{
	Ecode_t sc = nvm3_repack(NVM3_DEFAULT_HANDLE);
	return sc;
}

